<!--
 * @Author: Bobby
 * @Date: 2021-12-30 10:01:42
 * @LastEditTime: 2022-03-15 17:27:32
 * @LastEditors: Bobby
 * @Description:
 * @FilePath: \wms-v2\src\ve\elements\basic\uiDynamicForm\uiDynamicForm.vue
 * CIMC-V2
-->
<template>
  <template v-if="!hasPreview">
    <div class="ui-dynamic-form" style="overflow: hidden">
      <el-form ref="form" label-width="80px">
        <el-form-item :label="translateTitle('Ve.elements.动态输入')" style="width: 300px; float: left">
          <el-input v-model="testCode" disabled />
        </el-form-item>
        <el-form-item :label="translateTitle('Ve.elements.动态下拉')" style="width: 300px; float: left">
          <el-select v-model="testCode" disabled :placeholder="translateTitle('Ve.elements.动态下拉')" style="width: 100%">
            <el-option :label="translateTitle('Ve.elements.区域一')" value="shanghai" />
            <el-option :label="translateTitle('Ve.elements.区域二')" value="beijing" />
          </el-select>
        </el-form-item>
        <el-form-item :label="translateTitle('Ve.elements.动态日期')" style="width: 300px; float: left">
          <el-date-picker v-model="testCode" disabled :placeholder="translateTitle('Ve.elements.选择日期')" type="date" />
        </el-form-item>
        <el-form-item :label="translateTitle('Ve.elements.动态数字')" style="width: 300px; float: left">
          <el-input-number v-model="testNumber" disabled style="width: 100%" />
        </el-form-item>
      </el-form>
    </div>
  </template>
  <template v-else>
    <div :ref="'self' + info._id" v-ui-ref="vSetRef" class="ui-dynamic-form">
      <Widget :class="['grid cols-4']" :list="info.list" />
    </div>
  </template>
</template>
<script>
  import { translateTitle } from '@/utils/i18n'
  import { defineComponent, defineAsyncComponent } from 'vue'
  import { UiMixin, ElementsFormMixin, RefsInjectMixin, ConditionMixin } from '@ve/mixin'
  import COMPONENTS from '@ve/common/components'
  import isArray from 'lodash/isArray'
  import cloneDeep from 'lodash/cloneDeep'
  import request from '@/utils/request'
  import { GFCD } from '@/utils/utils'
  import { reArrayData } from '@ve/utils/extendData'

  import { processingConstant } from '@ve/utils/utils'
  import { componentId } from '@/utils/unique'
  import isEmpty from 'lodash/isEmpty'
  import trim from 'lodash/trim'
  import dayjs from 'dayjs'

  const componentARR = {
    10: 'uiInput',
    20: 'uiInput',
    30: 'uiInput',
    40: 'uiDate',
    50: 'uiDate',
    60: 'uiDateTimeInput',
    70: 'uiDateTimeInput',
  }

  export default defineComponent({
    name: 'UiDynamicForm',
    components: {
      // 使用异步组件
      Widget: defineAsyncComponent(() => import('@ve/components/widget.vue')),
    },
    mixins: [UiMixin, ElementsFormMixin, RefsInjectMixin, ConditionMixin],
    props: {
      requestFlag: {
        type: Number,
        default: 0,
      },
      info: {
        required: true,
        type: Object,
        default: function () {
          return {}
        },
      },
    },
    data: function () {
      return {
        testCode: '',
        testNumber: 0,
        dataSorce: {},
        lastNewval: {},
        defaultValues: [],
      }
    },
    computed: {
      requestData() {
        return this.info.data.requestData
      },
    },
    watch: {
      requestFlag: {
        handler() {
          this.renderDynamicForm(this)
        },
      },
      requestData: {
        deep: true,
        handler(newvalue) {
          this.renderDynamicForm(this, newvalue.data)
        },
      },
    },
    created() {
      if (!this.hasPreview) this.getInfo.list = []
      this.defaultValues = (this.getInfo.extension.defaultValues && this.getInfo.extension.defaultValues.value) || []
    },
    methods: {
      translateTitle,
      requestApi(options = {}, callback, cb) {
        if (!options.api || !options.method || !options.key) {
          return
        }
        let Request = {},
          requestValue = options.data
        requestValue.forEach((item) => {
          //处理下拉参数
          if (options.selectConfig && item.value === 'INPUT_OPTIONS') {
            Request[item.key] = processingConstant(this, options.selectConfig)
            return
          }
          let itemVal = item.value
          if (/{[^#{]+}/g.test(itemVal)) {
            //获取索引
            const index = itemVal.indexOf('}')
            //获取字段
            const field = itemVal.substring(2, index) + itemVal.substring(index + 1)
            //赋值
            itemVal = this.dataSorce[field]
          }
          //常量参数
          Request[item.key] = processingConstant(this, itemVal)
        })
        Request = { ...this.dataSorce, ...Request }
        //发起请求
        return request({
          url: GFCD('dams', 'domain') + options.api,
          method: 'post',
          data: {
            data: JSON.stringify(Request),
            method: options.method,
          },
        }).then((res) => {
          // 赋默认值
          this.assignDefaultValue()
          //添加回调
          callback && callback.call(this, res)
          // 事件回调
          cb && cb(res)
        })
      },
      // 赋默认值
      assignDefaultValue() {
        if (this.defaultValues.length) {
          const formSelf = this.vuiComponents[this.formId] && this.vuiComponents[this.formId].self
          const fromData = formSelf && formSelf.info.data.formData
          if (fromData) {
            this.defaultValues.forEach((item) => {
              if (!fromData[item.key]) {
                fromData[item.key] = processingConstant(this, item.value)
              }
            })
          }
        }
      },
      //异步执行渲染组件
      async renderDynamicForm(vm, data) {
        const $this = vm
        if (!$this.hasPreview) {
          return
        }
        // 删除之前渲染写入的正则规则
        this.delLotRules()

        if ($this.vuiComponents[$this.formId]) {
          const formItems = $this.vuiComponents[$this.formId].self.getInfo.data.formItems || {}
          for (let key in formItems) {
            if (formItems[key].indexOf('UiDynamicFormLOT_') !== -1) {
              delete formItems[key]
            }
          }
        }
        $this.getInfo.list = []
        const components = reArrayData([COMPONENTS.baseComs, COMPONENTS.wmsComs], [])
        let result = [],
          dataArr = data || $this.getInfo.data.requestData.data || []
        //拼接组装数据
        let CUR_LOT_list = []
        for (let i = 0; i < dataArr.length; i++) {
          const item = dataArr[i]
          if (item.INPUT_CONTROL_TYPE == '40') {
            continue
          }
          let obj = {}
          //判断类型
          obj = components.find((comp) => {
            let type = componentARR[item.INPUT_FORMAT_TYPE]
            //判断是不是下拉
            if (item.INPUT_OPTIONS) {
              type = 'uiSelect'
            }
            return comp.type === type
          })
          if (obj) {
            obj.formData = obj.formData || {}
            obj = cloneDeep(obj)
            //如果是下拉
            if (item.INPUT_OPTIONS) {
              //设置key和value
              obj.extension.labelField.value = ($this.info.extension.labelField || { value: 'label' }).value
              obj.extension.valueField.value = ($this.info.extension.valueField || { value: 'value' }).value
              //默认单选
              obj.extension.multiple.value = false
              //调到用接口获取options值
              await $this.requestApi(
                {
                  api: $this.info.extension.apiDropdown.value,
                  method: $this.info.extension.methodDropdown.value,
                  key: $this.info.extension.getDataKeyDropdown.value,
                  data: $this.getInfo.extension.requestDataDropdown.value,
                  selectConfig: item.INPUT_OPTIONS,
                },
                function (data) {
                  if (!data.data || !data.data[$this.info.extension.getDataKeyDropdown.value]) {
                    obj.extension.optionConfig.value = []
                    return
                  }
                  //选项
                  obj.extension.optionConfig.value = data.data[$this.info.extension.getDataKeyDropdown.value].data || []
                }
              )
            }
            // 如果是日期时间输入
            if (item.INPUT_FORMAT_TYPE == 70) {
              obj.extension.moduleType.value = 'dateTime'
            }

            //id
            obj._id = 'UiDynamicFormLOT_' + obj.type + '_' + componentId(6)
            //字段
            obj.extension.model.value = $this.getprefix($this) + item.LOT_SEQ
            //名称
            obj.extension.label.value = item.LOT_SEQ_NAME
            //赋默认值
            // if ($this.defaultValues.length) {
            //   console.log('批次属性赋默认值')
            //   const findDefalut = $this.defaultValues.find((defalutvalue) => {
            //     if (!this.getLotValue()[item.LOT_SEQ]) {
            //       // 如果当前表单没有值 则赋默认值
            //       return defalutvalue.key === item.LOT_SEQ
            //     }
            //   })
            //   if (findDefalut) {
            //     //没有默认值的情况赋值对象
            //     obj.type !== 'uiDate'
            //       ? (obj.extension.defaultValue = obj.extension.defaultValue || {})
            //       : (obj.extension.defaultDate = obj.extension.defaultDate || {})
            //     //赋默认值
            //     obj.type !== 'uiDate'
            //       ? (obj.extension.defaultValue.value = $this.getDefaultValue($this, findDefalut.value))
            //       : (obj.extension.defaultDate.value = $this.getDefaultValue($this, findDefalut.value))
            //   }
            // }
            //不是输入框执行
            if (!item.INPUT_OPTIONS) {
              //日期类型
              item.INPUT_FORMAT_TYPE == '40' && (obj.extension.selection.value = 'date')
              //日期时间类型
              item.INPUT_FORMAT_TYPE == '50' && (obj.extension.selection.value = 'datetime')
            }
            //验证相关
            if (item.INPUT_CONTROL_TYPE == '30' || $this.info.extension.disabled.value) {
              obj.extension.disabled.value = true
            }

            //必填验证
            if ($this.vuiComponents[$this.formId] && item.INPUT_CONTROL_TYPE == '20' && this.getIgnoreValidation(item.LOT_SEQ)) {
              $this.vuiComponents[$this.formId].ref.rules[item.LOT_SEQ] = [
                {
                  required: true,
                  message: translateTitle('Ve.utils.请输入必填信息'),
                  trigger: ['change', 'blur'],
                },
              ]
            }
            //添加进入数组
            if ($this.vuiComponents[$this.formId] && ['20', '30'].includes(String(item.INPUT_FORMAT_TYPE))) {
              //整数框
              let validateObj = {}
              if (item.INPUT_FORMAT_TYPE == '20') {
                validateObj = { pattern: /^-?[1-9]\d*$/, message: translateTitle('Ve.layout.请输入整数'), trigger: ['change', 'blur'] }
              }
              //数字框
              if (item.INPUT_FORMAT_TYPE == '30') {
                validateObj = { pattern: /^(-|\+)?\d+(\.\d+)?$/, message: translateTitle('Ve.layout.请输入数字'), trigger: ['change', 'blur'] }
              }
              if ($this.vuiComponents[$this.formId].ref.rules[item.LOT_SEQ]) {
                $this.vuiComponents[$this.formId].ref.rules[item.LOT_SEQ].push(validateObj)
              } else {
                $this.vuiComponents[$this.formId].ref.rules[item.LOT_SEQ] = [validateObj]
              }
            }
            if ($this.vuiComponents[$this.formId]) {
              $this.vuiComponents[$this.formId].self.getInfo.data.formItems = $this.vuiComponents[$this.formId].self.getInfo.data.formItems || {}
              $this.vuiComponents[$this.formId].self.getInfo.data.formItems[obj._id] = obj._id
            }
            // 记录组件回车控制
            if (item.CUR_LOT === 'Y') {
              // 如果当前组件打开了回车控制则添加记录
              CUR_LOT_list.push(obj._id)
            }
            obj.CUR_LOT_list = CUR_LOT_list
            // 将跳出批次属性组件的聚焦组件记录
            obj.extension.enterSelect = $this.info.extension.enterSelect
            // 记录父组件 以供最后一个组件回车时触发批次属性组件的回车事件
            obj.parentId = $this.info._id
            result.push(obj)
          }
        }
        $this.getInfo.CUR_LOT_list = CUR_LOT_list
        $this.getInfo.list = result

        // console.log('renderDynamicForm', data)
        setTimeout(() => {
          this.$pub(`SplitpaneResized_${this.previewPageId()}`, true)
        }, 1000)
      },
      getIgnoreValidation(key) {
        if (
          this.info.extension.IgnoreValidation &&
          this.info.extension.IgnoreValidation.value.length > 0 &&
          this.info.extension.IgnoreValidation.value.split(',').find((el) => el == key)
        ) {
          //忽略验证
          return false
        } else {
          return true
        }
      },
      getprefix(vm) {
        let returnObj = vm.info.extension.prefix || { value: '' }
        return returnObj.value || ''
      },
      dataSourceChange(newval) {
        // 判断是否有值改变
        let changeFlag = false
        Object.keys(newval).map((v) => {
          if (newval[v] !== this.lastNewval[v]) {
            changeFlag = true
          }
        })
        if (changeFlag) {
          this.lastNewval = cloneDeep(newval)
        } else {
          // 如果值未改变则不进行后续操作
          return
        }
        let _obj = {}
        Object.keys(this.getInfo.data.formData).map((v) => {
          _obj[v] = ''
        })
        let _mergeData = {}
        // 根据 getDataKey 筛选需要的数据
        if (!trim(this.info.dataSourceBind.getDataKey?.value)) {
          // 如果没有 getDataKey 则返回全量数据
          _mergeData = newval
        } else {
          const keyList = this.info.dataSourceBind.getDataKey?.value.split(',')
          isArray(keyList) &&
            keyList.forEach((item) => {
              item = trim(item)
              if (newval[item] !== undefined) {
                // 如果传过来的对象里面没有要取得值 则丢弃
                _mergeData[item] = newval[item]
              }
            })
        }
        let _data = isEmpty(_mergeData)
          ? _obj
          : {
              ...this.getInfo.data.formData,
              ..._mergeData,
            }
        this.getInfo.data.formData = _data
        this.dataSorce = _data
      },
      //获取自定义请求参数
      $getRequestData() {
        let _data = { ...this.dataSorce }
        const requestData = this.info.extension.requestData
        if (requestData && isArray(requestData.value)) {
          requestData.value.forEach((item) => {
            let itemVal = item.value
            if (/{[^#{]+}/g.test(itemVal)) {
              //获取索引
              const index = itemVal.indexOf('}')
              //获取字段
              const field = itemVal.substring(2, index) + itemVal.substring(index + 1)
              //赋值
              itemVal = this.dataSorce[field]
            }
            _data[item.key] = processingConstant(this, itemVal)
          })
        }
        return _data
      },
      requestOptionList(cb) {
        //this.dataSorce = this.getInfo.data.formData
        this.requestApi(
          {
            api: this.info.extension.api.value,
            method: this.info.extension.method.value,
            key: this.info.extension.getDataKey.value,
            data: this.getInfo.extension.requestData.value,
          },
          function (res) {
            const getDataKey = this.info.extension.getDataKey.value
            this.getInfo.data.requestData = isEmpty(getDataKey) ? res.data || {} : res.data[getDataKey] || {}
          },
          cb
        )
      },
      //获取默认值
      getDefaultValue(vm, value) {
        switch (value) {
          case '#CURRENT_DATE#':
            value = dayjs().format('YYYY-MM-DD')
            break
          case '#CURRENT_DATETIME#':
            value = dayjs().format('YYYY-MM-DD HH:mm:ss')
            break
          default:
            value = processingConstant(vm, value)
            break
        }
        return value
      },
      //禁用状态
      $isDisabled(flag) {
        //flag = true：禁用 flag = false：启用
        const list = this.getInfo.list || []
        for (let i = 0; i < list.length; i++) {
          if (!list[i].extension.disabled) {
            list[i].extension.disabled = {}
          }
          list[i].extension.disabled && (list[i].extension.disabled.value = flag)
        }
      },
      getLotValue() {
        // 1. 先查找到当前组件所在得表单组件
        // this里面有一个 formId 属性存储了当前组件所在的表单组件的 id，直接取来用即可
        // 通过 formId 在 vuiComponents 中找到表单组件的实例
        const formSelf = this.vuiComponents[this.formId] && this.vuiComponents[this.formId].self
        // 2. 在表单组件中获取LOT01 ~ LOT48的值，然后返回
        if (!formSelf) return {}
        let respObj = {}
        // 在表单实例中拿到表单的值
        const fromData = formSelf.info.data.formData
        // 将表单中的值写入返回对象并返回
        for (let i = 1; i < 49; i++) {
          if (i < 10) {
            respObj[`LOT0${i}`] = fromData[`LOT0${i}`]
          } else {
            respObj[`LOT${i}`] = fromData[`LOT${i}`]
          }
        }
        return respObj
      },
      // 删除表单中的批次属性的正则校验
      delLotRules() {
        const formRef = this.vuiComponents[this.formId] && this.vuiComponents[this.formId].ref
        console.log('formSelf -------- ', formRef)
        const formRules = formRef.rules
        if (!formRules) return
        for (let i = 1; i < 49; i++) {
          let lotKey = ''
          if (i < 10) {
            lotKey = `LOT0${i}`
          } else {
            lotKey = `LOT${i}`
          }
          if (formRules[lotKey]) {
            delete formRules[lotKey]
          }
        }
      },
    },
  })
</script>
<style scoped>
  .ui-dynamic-form {
    min-height: 20px;
  }
</style>
